from uuid import uuid1
import os
from jili.trade.constants import bs,openclose,status,ordertype
from jili.pos import fund,orderdetail,workingorder,position,positiondetail,tradedetail
sourceid = os.getpid()
from jili.core.printlog import print
from jili.tool.state import ismongo

if ismongo:
    from jili.data.obj import getmarketcode
from jili.trade.adapterapi import adpaterapi
class trade(adpaterapi):
    def __init__(self,brokerid, investid,adaptertype="ctp"):
        self.poss = {"byobj":{},"bybs":{"buy":{},"sell":{}}}
        self.posdetails={"byobj":{},"bybs":{"buy":{},"sell":{}},"bytradeid":{}}
        self.orders = {"byid":{},"byobj":{}}  # orderid map all
        self.tradedetails = {"byobj":{},"byorderid":{},"bytradeid":{}}
        self.workorders = {"byid":{},"byobj":{}}  # orderid map  trdaing
        self.fund = fund()
        self.frozenfunds={}
        self.error=[]

        self.onpos=""
        self.onposdetail = ""
        self.onfund=""
        self.onorder=""
        self.ontrade = ""
        self.onworkingorder=""
        self.onerr=""
        super(trade, self).__init__(brokerid, investid, adaptertype)
        self.setoncall("onqrypos",self.trade_onqrypos)
        self.setoncall("onqryposdetail", self.trade_onqryposdetail)
        self.setoncall("onqryfund", self.trade_onqryfund)
        self.setoncall("onqryorder", self.trade_onqryorder)
        self.setoncall("onqrytrade", self.trade_onqrytrade)
        self.setoncall("onorder", self.trade_onorder)
        self.setoncall("ontrade", self.trade_ontrade)
        self.setoncall("onerr", self.trade_onerr)
    def trade_onqrypos(self,p,seq):
        if seq==0:
            self.poss={"byobj":{},"bybs":{"buy":{},"sell":{}}}
        pos = position()
        pos.update(p)
        obj = pos.obj
        bs=pos.bs
        self.poss["bybs"][bs][obj]=pos
        self.poss["byobj"][obj][bs]=pos
    def trade_onqryposdetail(self,p,seq):
        if seq == 0:
            self.posdetails = {"byobj": {}, "bybs": {"buy": {}, "sell": {}}, "bytradeid": {}}
        pos = positiondetail()
        pos.update(p)
        obj = pos.obj
        bs = pos.bs
        tradeid=pos.tradeid
        self.posdetails["bybs"][bs][obj][tradeid] = pos
        self.posdetails["byobj"][obj][bs][tradeid] = pos
        if tradeid not in self.posdetails["bytradeid"].keys():
            self.posdetails["bytradeid"][tradeid]=[pos]
        else:
            self.posdetails["bytradeid"][tradeid].append(pos)
    def trade_onqryfund(self,f):
        self.fund.update(f)
    def trade_onqryorder(self,o):
        oo=orderdetail()
        oo.update(o)
        obj=oo.obj
        bs=oo.bs
        orderid=oo.orderid
        openclose=oo.openclose
        self.orders["byid"][orderid]=oo
        self.orders["byobj"][obj][bs][openclose][orderid]=oo
        stat=oo.status
        if stat in [status.working,status.parttraded]:
            wo=workingorder()
            wo.setdict(oo)
            self.workorders["byid"][orderid]=wo
            self.workorders["byobj"][obj][bs][openclose][orderid]=wo
        elif stat in [status.alltraded,status.canceled,status.rejected]:
            self.workorders["byid"].pop(orderid,None)
            if obj in self.workorders["byobj"].keys():
                if bs in self.workorders["byobj"][obj].keys():
                    if openclose in self.workorders["byobj"][obj][bs].keys():
                        self.workorders["byobj"][obj][bs].pop(orderid)
    def trade_onqrytrade(self,t):
        tt=tradedetail()
        tt.update(t)
        obj=tt.obj
        orderid=tt.orderid
        bs=tt.bs
        openclose=tt.openclose
        tradeid=tt.tradeid
        self.tradedetails["byobj"][obj][bs][openclose][tradeid]=tt
        self.tradedetails["byorderid"][orderid][tradeid]=tt
        self.tradedetails["bytradeid"][orderid]=tt
    def trade_onorder(self,o):
        oo=orderdetail()
        oo.update(o)
        obj=oo.obj
        bs=oo.bs
        orderid=oo.orderid
        openclose=oo.openclose
        self.orders["byid"][orderid]=oo
        self.orders["byobj"][obj][bs][openclose][orderid]=oo
        stat=oo.status
        if stat in [status.working,status.parttraded]:
            wo=workingorder()
            wo.setdict(oo)
            self.workorders["byid"][orderid]=wo
            self.workorders["byobj"][obj][bs][openclose][orderid]=wo
        elif stat in [status.alltraded,status.canceled,status.rejected]:
            self.workorders["byid"].pop(orderid,None)
            if obj in self.workorders["byobj"].keys():
                if bs in self.workorders["byobj"][obj].keys():
                    if openclose in self.workorders["byobj"][obj][bs].keys():
                        self.workorders["byobj"][obj][bs].pop(orderid)
        self.update_by_orderdetail(o)
    def trade_ontrade(self,t):
        tt=tradedetail()
        tt.update(t)
        obj=tt.obj
        orderid=tt.orderid
        bs=tt.bs
        openclose=tt.openclose
        tradeid=tt.tradeid
        self.tradedetails["byobj"][obj][bs][openclose][tradeid]=tt
        self.tradedetails["byorderid"][orderid][tradeid]=tt
        self.tradedetails["bytradeid"][orderid]=tt
        self.update_by_tradedetail(t)
    def update_by_orderdetail(self,oo):
        """
        update position by orderdetail
        """
        obj = oo.obj
        bs = oo.bs
        oc=oo.openclose
        if oc!=openclose.open:
            if obj in self.poss["byobj"]:
                if bs in self.poss["byobj"][obj]:
                    pos=self.poss["byobj"][obj][bs]
                    pos.update_orderdetail(oo)
        self.fund.update_orderdetail(oo)
    def update_by_tradedetail(self,oo):
        """
        update positiondetail by orderdetail
        """
        obj = oo.obj
        bs = oo.bs
        if obj in self.poss["byobj"]:
            if bs in self.poss["byobj"][obj]:
                pos = self.poss["byobj"][obj][bs]
                pos.update_tradedetail(oo)
        self.fund.update_tradedetail(oo)
    def trade_onerr(self,e):
        self.error.append(e)
    def getorderid(self):
        return uuid1().hex
    def submitorder(self,obj,bs,openclose,price,qty,marketcode,timekey=None,orderid="",oncall=""):
        order={
            "cmd":"submitorder",
            "obj":obj,
            "bs":bs,
            "openclose":openclose,
            "price":price,
            "qty":qty,
            "marketcode":marketcode,
        }
        if orderid=="":
            order["orderid"]=self.getorderid()
        return self.call(order,issync=False,oncall=oncall)

    def submitorder_sync(self, obj, bs, openclose, price, qty, marketcode,timekey=None,orderid=""):
        order = {
            "cmd": "submitorder",
            "obj": obj,
            "bs": bs,
            "openclose": openclose,
            "price": price,
            "qty": qty,
            "marketcode": marketcode
        }
        if orderid == "":
            order["orderid"] = self.getorderid()
        return self.call(order)
    def cancelorder_sync(self,orderid):
        if orderid in self.workorder["byid"].keys():
            req = {
                "cmd": "cancelorder",
                "orderid": orderid,
                "sys_orderid": self.workorder["byid"]["orderid"]["sys_orderid"],
                "obj": self.workorder["byid"]["orderid"]["obj"],
                "marketcode":self.workorder["byid"]["orderid"]["marketcode"]
            }
            return self.call(req)
        else:
            return {}

    def cancelorder(self,orderid="",oncall=""):
        if orderid!="":
            if orderid in self.workorder["byid"].keys():
                req={
                    "cmd":"cancelorder",
                    "orderid":orderid,
                    "sys_orderid":self.workorder["byid"]["orderid"]["sys_orderid"],
                    "obj": self.workorder["byid"]["orderid"]["obj"],
                    "marketcode": self.workorder["byid"]["orderid"]["marketcode"]
                }
                return self.call(req,issync=False, oncall=oncall)
            else:
                return -1,False,{}
        else:
            for k,v in self.workorder["byid"].items():
                req = {
                    "cmd": "cancelorder",
                    "orderid": k,
                    "sys_orderid": v["sys_orderid"]
                }
                a1,a2,a3=self.call(req,issync=False, oncall=oncall)
            return 1,True,{}
    def qryfund(self,oncall=""):
        req = {
            "cmd": "qryfund",
        }
        return self.call(req, issync=False, oncall=oncall)
    def qrypos(self,oncall=""):
        req = {
            "cmd": "qrypos",
        }
        return self.call(req, issync=False, oncall=oncall)
    def qryorder(self,oncall=""):
        req = {
            "cmd": "qryorder",
        }
        return self.call(req, issync=False, oncall=oncall)
    def qrytrade(self,oncall=""):
        req = {
            "cmd": "qrytrade",
        }
        return self.call(req, issync=False, oncall=oncall)
